﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using pub.Interop;
using pub.NET20Fix;
using todo.Properties;

namespace todo
{
    internal class LoadMask : IDisposable
    {
        private ContainerControl container;
        private Thread thread;
        private Panel panel;
        private IntPtr containerHandle;
        private ApplicationContext threadContext;
        private EventWaitHandle ewh;

        private Control maskControl;

        public LoadMask(ContainerControl container, Control maskControl = null)
        {
            ewh = new ManualResetEvent(false);

            threadContext = new ApplicationContext();

            this.container = container;
            containerHandle = container.Handle;

            this.maskControl = maskControl;

            this.thread = new Thread(ThreadProc);
            this.thread.SetApartmentState(ApartmentState.STA);
            this.thread.Start();

            ewh.WaitOne();
            ewh.Close();
        }

        private void ThreadProc()
        {
            panel = new Panel();
            panel.BackColor = SystemColors.Window;
            panel.Left = 0;
            panel.Top = 0;
            panel.Width = 800;
            panel.Height = 600;

            var pictureBox = new PictureBox();
            pictureBox.Image = Resources.wait;
            pictureBox.Location = new Point(12, 12);
            pictureBox.Name = "pictureBox1";
            pictureBox.Size = new Size(16, 16);
            pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
            pictureBox.TabIndex = 1;
            pictureBox.TabStop = false;

            panel.Controls.Add(pictureBox);

            var label = new Label();
            label.AutoSize = true;
            label.Font = new Font("Consolas", 9.75F, FontStyle.Regular,
                    GraphicsUnit.Point, ((0)));
            label.Location = new Point(34, 13);
            label.Name = "label1";
            label.Size = new Size(77, 15);
            label.TabIndex = 0;
            label.Text = "Loading...";

            panel.Controls.Add(label);
            panel.Visible = false;


            //pictureBox.Parent = this.container;
            Debug.Print("panel with handle: " + panel.Handle);
            Win32.SetParent(panel.Handle, containerHandle);

            ewh.Set();
            Application.Run(threadContext);

            panel.Dispose();
        }

        public void Show()
        {
            Debug.Print("loadmask.show");
            if (this.maskControl == null)
            {
                var w = this.container.ClientSize.Width;
                var h = this.container.ClientSize.Height;
                panel.Invoke((Action) (() => {
                    panel.Width = w;
                    panel.Height = h;
                    panel.Show();
                }));
            }
            else
            {
                var l = this.maskControl.Left;
                var t = this.maskControl.Top;
                var w = this.maskControl.Width;
                var h = this.maskControl.Height;
                panel.Invoke((Action) (() => {
                    panel.Left = l;
                    panel.Top = t;
                    panel.Width = w;
                    panel.Height = h;
                    panel.Show();
                }));
            }
        }

        public void Hide()
        {
            panel.Invoke((Action) (() => panel.Hide()));
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~LoadMask()
        {
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.threadContext == null)
                {
                    return;
                }
                threadContext.ExitThread();
                threadContext = null;
            }
        }
    }
}